import md5 from "md5";
import CryptoJS from "crypto-js";
import qs from "qs";

// 校验手机号码格式
const checkMobile = () => {
  return /^[1][3,4,5,6,7,8,9][0-9]{9}$/;
};

// 校验电话号码格式
const checkPhone = () => {
  return /^(0\d{2,3}-?)?\d{7,8}$/;
};

// des 加密 对应后台加密方法
const encryptedDES = (plaintext: any): string => {
  const jms = md5("29DAAD0A66C62BA3").toUpperCase();
  const ssb = CryptoJS.MD5(jms).toString(CryptoJS.enc.Hex).substring(0, 8).toUpperCase();
  const keyHex = CryptoJS.enc.Utf8.parse(ssb);
  const ivHex = CryptoJS.enc.Utf8.parse(ssb);
  const encrypted = CryptoJS.DES.encrypt(plaintext, keyHex, {
    iv: ivHex,
    mode: CryptoJS.mode.CBC,
    padding: CryptoJS.pad.Pkcs7
  });
  return encrypted.ciphertext.toString().toUpperCase();
};

// des解密
const decryptByDESModeCBC = (ciphertext2: any): string => {
  const jms = md5("29DAAD0A66C62BA3").toUpperCase();
  const ssb = CryptoJS.MD5(jms).toString(CryptoJS.enc.Hex).substring(0, 8).toUpperCase();
  const keyHex = CryptoJS.enc.Utf8.parse(ssb);
  const ivHex = CryptoJS.enc.Utf8.parse(ssb);
  const csg = CryptoJS.enc.Hex.parse(ciphertext2);
  const decrypted = CryptoJS.DES.decrypt({ ciphertext: csg }, keyHex, {
    iv: ivHex,
    mode: CryptoJS.mode.CBC,
    padding: CryptoJS.pad.Pkcs7
  });
  return decrypted.toString(CryptoJS.enc.Utf8);
};

// 校验证件号码
// eslint-disable-next-line complexity
const validateuIdCardNo = (uIdCardType: any, uIdCardNo: any) => {
  if (!uIdCardType) {
    return Promise.reject(new Error("请先选择证件类型！"));
  }

  if (uIdCardType === "1") {
    // eslint-disable-next-line @typescript-eslint/no-use-before-define
    if (!isCardID(uIdCardNo)) {
      return Promise.reject(new Error("身份证格式不正确！"));
    }
  }

  if (uIdCardType === "2") {
    const sergeant = /^[\u4E00-\u9FA5](字第)([0-9a-zA-Z]{4,8})(号?)$/;
    if (!sergeant.test(uIdCardNo)) {
      return Promise.reject(new Error("军官证格式不正确！"));
    }
  }

  if (uIdCardType === "3") {
    const hz1 =
      /^1[45][0-9]{7}|K[0-9]{8}|[M][A][0-9]{7}|[K][J][0-9]{7}|A[0-9]{8}|E[0-9]{8}|G[0-9]{8}|P[0-9]{7}|S[0-9]{7,8}|D[0-9]+$/;
    const hz2 = /^([a-zA-z]|[0-9]){5,17}$/;
    const hz3 = /^[A-Za-z0-9]{8,}$/;
    if (!hz1.test(uIdCardNo) && !hz2.test(uIdCardNo) && !hz3.test(uIdCardNo)) {
      return Promise.reject(new Error("护照格式不正确！"));
    }
  }

  if (uIdCardType === "4") {
    const gw1 = /^[a-zA-Z]{3}[0-9]{12}$/;
    if (!gw1.test(uIdCardNo)) {
      return Promise.reject(new Error("外国人居住证格式不正确！"));
    }
  }

  if (uIdCardType === "5") {
    const tel1 = /^[0-9]{8}$/;
    const tel2 = /^[0-9]{10}$/;
    const tel3 = /^\d{8}|^[a-zA-Z0-9]{10}|^\d{18}$/;
    const test4 = /^\d{8}$|^\d{10}[a-zA-Z]$|^\d{18}$/;
    const test5 = /^\d{6}(18|19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dXx]$/;
    if (
      !tel1.test(uIdCardNo) &&
      !tel2.test(uIdCardNo) &&
      !tel3.test(uIdCardNo) &&
      !test4.test(uIdCardNo) &&
      !test5.test(uIdCardNo)
    ) {
      return Promise.reject(new Error("台胞证格式不正确！"));
    }
  }

  if (uIdCardType === "6") {
    const ga1 = /^[HMhm]{1}([0-9]{10}|[0-9]{8})$/;
    const ga2 = /^([A-Z]\d{6,10}(\(\w{1}\))?)$/;
    const ga3 = /^[A-Z]\d{8}$|^[A-Z]\d{10}$/;
    const ga4 = /^\d{6}(18|19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dXx]$/;
    const ga5 = /^(\d{8})(\([A-Za-z0-9]{1,2}\))?$/;
    if (!ga1.test(uIdCardNo) && !ga2.test(uIdCardNo) && !ga3.test(uIdCardNo) && !ga4.test(uIdCardNo) && !ga5.test(uIdCardNo)) {
      return Promise.reject(new Error("港澳回乡证格式不正确！"));
    }
  }
  return Promise.resolve();
};

// 验证身份证
const isCardID = (sId: any): boolean => {
  const aCity: any = {
    11: "北京",
    12: "天津",
    13: "河北",
    14: "山西",
    15: "内蒙古",
    21: "辽宁",
    22: "吉林",
    23: "黑龙江",
    31: "上海",
    32: "江苏",
    33: "浙江",
    34: "安徽",
    35: "福建",
    36: "江西",
    37: "山东",
    41: "河南",
    42: "湖北",
    43: "湖南",
    44: "广东",
    45: "广西",
    46: "海南",
    50: "重庆",
    51: "四川",
    52: "贵州",
    53: "云南",
    54: "西藏",
    61: "陕西",
    62: "甘肃",
    63: "青海",
    64: "宁夏",
    65: "新疆",
    71: "台湾",
    81: "香港",
    82: "澳门",
    91: "国外"
  };
  let iSum = 0;
  if (!/^\d{17}(\d|x)$/i.test(sId)) {
    return false;
  }
  // eslint-disable-next-line no-param-reassign
  sId = sId.replace(/x$/i, "a");
  // eslint-disable-next-line no-eq-null
  if (aCity[Number.parseInt(sId.substr(0, 2), 10)] === null) {
    return false;
  }
  const sBirthday = `${sId.substr(6, 4)}-${Number(sId.substr(10, 2))}-${Number(sId.substr(12, 2))}`;
  const d = new Date(sBirthday.replace(/-/g, "/"));
  if (sBirthday !== `${d.getFullYear()}-${d.getMonth() + 1}-${d.getDate()}`) {
    return false;
  }
  // eslint-disable-next-line no-plusplus
  for (let i = 17; i >= 0; i--) {
    iSum += (2 ** i % 11) * Number.parseInt(sId.charAt(17 - i), 11);
  }
  return iSum % 11 === 1;
};

// 校验密码
const validateuPwd = (pwd: any, value: any) => {
  // eslint-disable-next-line prefer-regex-literals
  const strongRegex = new RegExp("^(?=^.{8,40}$)(?=.*[A-Z])(?=.*[a-z])(?=.*[0-9])(?=^[^\u4E00-\u9FA5]*$).*$", "g");
  const ispass = strongRegex.test(value);
  if (!ispass) {
    return Promise.reject(new Error("密码由大于等于8位大小写字母、数字或其他特殊字符组成、不能包含中文名"));
  } else if (pwd !== value) {
    return Promise.reject(new Error("密码和确认密码不一样！"));
  }
  return Promise.resolve();
};

// 字符串超过多少长度用省略号代替显示
const stringOmit = (data: string, len: number = 10): string => {
  if (!data) {
    return "";
  }
  if (data.length <= len) {
    return data;
  }
  return `${data.substring(0, len)}...`;
};

const isVoid = (value: unknown) => value === undefined || value === null || value === "" || value === 0;

// 去除空值的对象返回有值的所有对象
const clearObject = (data: { [key: string]: unknown }) => {
  const result = { ...data };
  Object.keys(result).forEach(key => {
    const value = result[key];
    if (isVoid(value)) {
      // eslint-disable-next-line @typescript-eslint/no-dynamic-delete
      delete result[key];
    }
  });
  return result;
};

// 获取对象序列化信息： name=112&age=33&sex=1
const getParData = (data: { [key: string]: unknown }) => {
  return qs.stringify(clearObject(data));
};

export {
  checkMobile,
  checkPhone,
  decryptByDESModeCBC,
  encryptedDES,
  validateuIdCardNo,
  validateuPwd,
  stringOmit,
  clearObject,
  getParData
};
